package net.esj.basic.dao.hibernate.recorder;

import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import net.esj.basic.dao.Dao;
import net.esj.basic.dao.DaoProxy;
import net.esj.basic.pojo.PrimaryKey;
import net.esj.basic.pojo.Updater;

import org.springframework.beans.BeanUtils;

public abstract class AbstractPojoRecoder<T extends Serializable> implements Cloneable,Serializable,PrimaryKey{

	protected Object backUp;

	protected boolean loaded = false;
	
	protected void backUp(){
		try {
			backUp = this.clone();
		} catch (CloneNotSupportedException e) {
			backUp = null;
		}
	}
	
	public void reload(){
		Dao dao = DaoProxy.getProxy(Dao.class);
		backUp= dao.get((Serializable)getId(), getClass());
		reset();
	}
	
	public void reset(){
		if(backUp==null){
			return;
		}
		PropertyDescriptor[] pds =BeanUtils.getPropertyDescriptors(this.getClass());
		for(PropertyDescriptor pd:pds){
			Method writeMethod = pd.getWriteMethod();
			Method readMethod = pd.getReadMethod();
			if(writeMethod!=null && readMethod!=null){
				try {
					Object newValue = readMethod.invoke(backUp);
					writeMethod.invoke(this, newValue);
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	public void notifyBackUp(Updater updater){
		if(backUp==null){
			return;
		}
		for(String key : updater.getProperties()){
			PropertyDescriptor pd =BeanUtils.getPropertyDescriptor(this.getClass(), key);
			if(pd!=null){
				Method readMethod = pd.getReadMethod();
				Method writeMethod = pd.getWriteMethod();
				
				if(readMethod!=null && writeMethod!=null){
					try {
						Object newValue = readMethod.invoke(this);
						writeMethod.invoke(backUp, newValue);
					} catch (IllegalArgumentException e) {
						e.printStackTrace();
					} catch (IllegalAccessException e) {
						e.printStackTrace();
					} catch (InvocationTargetException e) {
						e.printStackTrace();
					}
				}
			}
			reset();
		}
	}
}
